package me.yxy.mobanddd.components;

import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Bean处理工具，主要是解决spring架构与DDD之间八字不合的一些问题，相当于一个简单的适配组件
 */
public class BeanTools {

    /**
     * 生成一个列表，其属性基于sourceList生成
     * @param sourceList
     * @param <B>
     * @return
     */
    public static List copyList(List sourceList,Class<?> targetClass){

        if(ObjectUtils.isEmpty(sourceList)){
            return new ArrayList<>(0);
        }

        List targetList = new ArrayList<>(sourceList.size()*2);
        for (Object source: sourceList) {
            try {
                Object targetObj = Class.forName(targetClass.getCanonicalName()).newInstance();

                //网上还有另外i一种方案是 JSON.parseArray(JSON.toJSONString(source), People.class)； 据说性能更好
                BeanUtils.copyProperties(source,targetObj);
                targetList.add(targetObj);
            } catch (Exception e) {
            }
        }

        return targetList;
    }

    /**
     * 将一个DTO列表转换成对应的领域模型
     * @param dtoList
     * @param <B>
     * @return
     */
    public static List toDomains(List dtoList,Class<?> domainClz){

        if(ObjectUtils.isEmpty(dtoList)){
            return new ArrayList<>(0);
        }

        List domainList = new ArrayList<>(dtoList.size()*2);
        for (Object dto: dtoList) {
            try {
                Method fromMethod = domainClz.getMethod("from", Object.class);
                Object domainObj = fromMethod.invoke(null,new Object[]{dto});
                domainList.add(domainObj);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            }
        }

        return domainList;
    }


    public static void main(String[] args) {

    }

    /**
     * 将DTO数据拷贝到domainEntity中
     * @param dto
     * @param domainEntity
     */
    public static void copyProperties(Object dto, Object domainEntity) {
        if(ObjectUtils.isEmpty(dto) || ObjectUtils.isEmpty(domainEntity)){
            return;
        }

        Field[] dtoFields =  dto.getClass().getDeclaredFields();
        if(ObjectUtils.isEmpty(dtoFields)){
            return;
        }

        for (Field dtoField : dtoFields) {
            try {
                Field domainField = domainEntity.getClass().getDeclaredField(dtoField.getName());
                if(!domainField.getType().equals(dtoField.getType())){
                    continue;
                }

                dtoField.setAccessible(true);
                domainField.setAccessible(true);
                Object fieldValue =  dtoField.get(dto);
                domainField.set(domainEntity,fieldValue);
            } catch (IllegalAccessException | NoSuchFieldException e) {

            }
        }
    }
}
